"""
这是一个经典的概率问题：
天气预报说，在今后的三天中，每一天下雨的概率均为40%，请问这三天中恰有两天下雨的概率是多少？
这个问题不能用古典概型来求解，因为恰有一天下雨和恰有两天下雨的可能性不一样，不符合古典概型的要求。
那么怎么用 Python 来模拟这种 40% 的概率和三天中两天下雨的情况呢？
可以用代码随机产生 0 ～ 9 之间的整数随机数，用 1、2、3、4 表示下雨，用 5、6、7、8、9、0 表示不下雨。

由于以三天为一组，所以我们每次生成一个三位的数字串。
用 NumPy 生成随机值（控制在三位数字），由于百位以内不够三位，我们用 zfill 在前面补 0，就实现了一次生成三天的情况。
然后计算这些数字字符中 1 ～ 4（意为下雨）的数量，筛选值为 2（意为两天下雨）的数据，最后与总数据量（天数）相比得到结果。
"""
"""
思考 1: 能否用古典概型来求解，为什么？
不能，恰有一天下雨和恰有两天下雨的可能性不一样，不符合古典概型。

思考 2: 你如何模拟每一天下雨为40%的概率？
可以用计算机产生 0 到 9 之间的整数随机数，用 1，2，3, 4 表示下雨，用 5，6，7，8，9, 0 表示不下雨。

思考3: 试验时，用什么数来表示三天中下雨这一事件？
因为是3天，所以每三个随机数作为一组
"""
""" 古典概型
定义
    （1） 试验中所有可能出现的基本事件只有有限个；
    （2） 试验中每个基本事件出现的可能性相等。
    具有以上两个特点的概率模型是大量存在的，这种概率模型称为古典概率模型，简称古典概型，也叫等可能概型。
    
特点
    古典概型的特点
        有限性（所有可能出现的基本事件只有有限个）
        等可能性（每个基本事件出现的可能性相等）
    基本事件的特点
        （1）任何两个基本事件是互斥的。
        （2）任何事件（除不可能事件）都可以表示成基本事件的和。
古典概型的判断
    一个试验是否为古典概型，在于这个试验是否具有古典概型的两个特征——有限性和等可能性，只有同时具备这两个特点的概型才是古典概型。
"""
import pandas as pd
import numpy as np

rng = np.random.default_rng()

days = 1000000
arr = rng.integers(0, 1000, days)  # 生成 100000 个 0 - 999 的数

df = pd.DataFrame().assign(x=arr).astype(str)
# print(df)

# 将两位数的前边补 0 凑成 3位数
df = df.assign(x=lambda d: d.x.str.zfill(3))
# print(df)

# 统计 x 列中的数字有 1 - 4 的数中出现的次数
df = df.assign(a=lambda d: d.x.str.count(r"1|2|3|4"))
# print(df)

# 筛选只出现两次的情况
df = df.query("a == 2")
print(df)

# 3天只出现2天下雨的概率
print("3天只出现2天下雨的概率：", round(df.shape[0] / days, 3))


"""
验证一下：

先在三天里面选下雨的两天即 C(3, 2) = 3 * 2 / 2 = 3
有两天下雨一天不下的概率 ＝ 0.4 * 0.4 * 0.6 = 0.096
这三天中恰好有两天下雨的概率 ＝ 0.096 * 3 ＝ 0.288

概率公式：
C(n, k) = n(n - 1)(n - 2)(n - k + 1) / k! ，其中 k ≤ n。
例如，C(12, 3) = 12 × 11 × 10 / 3! = 1320 / (3×2×1) = 1320 / 6 = 220。
"""